#include <wx/spinctrl.h>
#include "SudokuSolverMain.h"
#include "functions.h"

//A structure for holding all the information used by each square.
struct square
{
    int solved;
    int possible[9];
};

void solve(wxSpinCtrl *grid[9][9])
{

    //An array holding information for solving
    square new_grid[9][9];

    //Copies the information from "grid" to "new_grid"
    loadGrid(grid, new_grid);


    rule_1(new_grid);  //No number can exist in two places in any one row, column or sub-grid.
    rule_2(new_grid);  //If there is only one possible value for a square, it contains that value.
    rule_3(new_grid);  //If there is only one place in a row, column or subgrid that a number fits, it goes there.


    //Output new information to original grid
    for(int row=0; row<9; row++)
    {
        for(int col=0; col<9; col++)
        {
            grid[row][col]->SetValue(new_grid[row][col].solved);
        }
    }
}

void loadGrid(wxSpinCtrl *grid[9][9], square new_grid[9][9])
{
    //Loop through the grid...
    for(int row=0; row<9; row++)
    {
        for(int col=0; col<9; col++)
        {
            new_grid[row][col].solved = grid[row][col]->GetValue();  //new_grid[][].solved is used to hold the value in the square

            if(new_grid[row][col].solved == 0)  //If the current square has not been solved...
            {
                for(int i=0; i<9; i++)  //then loop through the array holding possible numbers...
                {
                    new_grid[row][col].possible[i]=1;  //and tell it that they are all possible.
                }
            }
            else  //if the current square has been solved...
            {
                for(int i=0; i<9; i++)  //then loop through the array holding possible numbers...
                {
                    new_grid[row][col].possible[i]=0;  //and tell it that none of them are possible.
                }
            }
        }
    }
}

void rule_1(square new_grid[9][9])
{
    for(int row=0; row<9; row++)
    {
        for(int col=0; col<9; col++)
        {
            int myValue = new_grid[row][col].solved; //Store the value in "solved"...

            if(myValue>0)  //If the square is solved...
            {
                for(int r=0; r<9; r++)
                {   //Loops through all the squares in the same column and tells them
                    //they can't be the same.
                    if(r!=row) {new_grid[r][col].possible[myValue-1]=0;}
                }
                for(int c=0; c<9; c++)
                {   //Loops through all the squares in the same row and tells them
                    //they can't be the same.
                    if(c!=col) {new_grid[row][c].possible[myValue-1]=0;}
                }

                int subgrid_row;  //A subgrid is a 3x3 section in a puzzle
                int subgrid_col;  //These variables track which one the current tile is in.

                if(row<=2) {subgrid_row = 0;}  //Rows 0-2 belong to the first row of subgrids
                else if(row>=3 && row<=5) {subgrid_row = 1;}  //Rows 3-5 belong to the second row of subgrids
                else if(row>=6 && row<=8) {subgrid_row = 2;}  //Rows 6-8 belong to the third row of subgrids

                if(col<=2) {subgrid_col = 0;}
                else if(col>=3 && col<=5) {subgrid_col = 1;}
                else if(col>=6 && col<=8) {subgrid_col = 2;}

                for(int r=subgrid_row*3; r<(subgrid_row*3)+3; r++)
                {
                    for(int c=subgrid_col*3; c<(subgrid_col*3)+3; c++)
                    {   //Loop through the tiles in the current subgrid
                        //and tell them they can't be the same as this one.
                        if(c!=col && r!=row)
                        {
                            new_grid[r][c].possible[myValue-1]=0;
                        }
                    }
                }

            }  //if(myValue>0)
        }
    }
}

bool rule_2(square new_grid[9][9])
{
    // -=- SOLVE MENTHOD 1 -=-
    //If there is only one possible value for a square, it contains that value.
    for(int row=0; row<9; row++)
    {
        for(int col=0; col<9; col++)  //Loop through squares
        {
            if(new_grid[row][col].solved==0)  //If the current square is unsolved
            {
                int numberPossible = 0;  //Used to hold the number of possible values for the square

                for(int i=0; i<9; i++)  //Loop through possible values...
                {
                    numberPossible += new_grid[row][col].possible[i];  //and add 1 to numberPossible for each
                }

                if(numberPossible==1)  //if there was only one possible value
                {
                    for(int i=0; i<9; i++)  //loop through the possible values
                    {
                        if(new_grid[row][col].possible[i]==1)  //if we've found the correct one
                        {
                            new_grid[row][col].solved = i+1;  //Solve the square
                            return true;

                            for(int r=0; r<9; r++)
                            {   //Loops through all the squares in the same column and tells them
                                //they can't be the same.
                                if(r!=row) {new_grid[r][col].possible[i]=0;}
                            }
                            for(int c=0; c<9; c++)
                            {   //Loops through all the squares in the same row and tells them
                                //they can't be the same.
                                if(c!=col) {new_grid[row][c].possible[i]=0;}
                            }

                        }  //if(new_grid[row][col].possible[i]==1)

                    }  //for(int i=0; i<9; i++)

                }  //if(numberPossible==1)

            }  //if(new_grid[row][col].solved==0)
        }
    } //END OF SOLVE METHOD 1
    return false;
}

bool rule_3(square new_grid[9][9])
{
    // -=- SOLVE METHOD 2 -=-
    //If there is only one place in a row, column or subgrid that a number fits, it goes there.
    int canBe[9];

    for(int row=0; row<9; row++)
    {  //Loop through all the rows...
        for(int i=0; i<9; i++) {canBe[i]=0;}  //Reset canBe

        for(int col=0; col<9; col++) //Loop through the tiles in the row
        {
            for(int i=0; i<9; i++) //Loop though the possible values for the current tile
            {
                canBe[i] += new_grid[row][col].possible[i];  //Tell it that the number "i" is possible in this square
            }
        }

        for(int i=0; i<9; i++)  //Loop through the possible values
        {
            if(canBe[i]==1)  //If only one square in this row can hold the number...
            {
                for(int col=0; col<9; col++)  //Loop through the tiles in this row
                {
                    if(new_grid[row][col].possible[i]==1)  //And when we find the one that the number is possible in...
                    {
                        new_grid[row][col].solved = i+1;  //Solve the tile with that number.
                        return true;
                    }
                }

            }
        }
    }

    for(int col=0; col<9; col++)
    {
        for(int i=0; i<9; i++) {canBe[i]=0;}

        for(int row=0; row<9; row++)
        {
            for(int i=0; i<9; i++)
            {
                canBe[i] += new_grid[row][col].possible[i];
            }
        }

        for(int i=0; i<9; i++)
        {
            if(canBe[i]==1)
            {
                for(int row=0; row<9; row++)
                {
                    if(new_grid[row][col].possible[i]==1)
                    {
                        new_grid[row][col].solved = i+1;
                        return true;
                    }
                }

            }
        }
    }

    for(int subgrid_row=0; subgrid_row<3; subgrid_row++)  //Loop through each row of subgrids
    {
        for(int subgrid_col=0; subgrid_col<3; subgrid_col++)  //Loop through the subgrids in the current row.
        {

            for(int i=0; i<9; i++) {canBe[i]=0;}  //Clear canBe

            for(int r=subgrid_row*3; r<(subgrid_row*3)+3; r++) //Loop through the rows in this subgrid
            {
                for(int c=subgrid_col*3; c<(subgrid_col*3)+3; c++)  //Loop through the squares in this row of the subgrid...
                {
                    for(int i=0; i<9; i++)  //Loop through the possible values for the current square
                    {
                        canBe[i] += new_grid[r][c].possible[i];  //Tell it that the number "i" is possible in this square
                    }
                }
            }

            for(int i=0; i<9; i++)  //Loop through possible values
            {
                if(canBe[i]==1)  //If the current number is only possible in one square...
                {
                    for(int r=subgrid_row*3; r<(subgrid_row*3)+3; r++)  //Loop through each row of tiles in the subgrid
                    {
                        for(int c=subgrid_col*3; c<(subgrid_col*3)+3; c++)  //Loop through the squares in this row of the subgrid...
                        {
                            if(new_grid[r][c].possible[i]==1)  //If the number is possible in this square
                            {
                                new_grid[r][c].solved = i+1;  //Assign the number to this square
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }  //END OF SOLVE METHOD 2
    return false;
}
